/*
@file: scanner.l
@author: ZZH
@date: 2022-03-29
@info: 
*/
%option nodefault yylineno noyywrap

%option stack
%pointer

%{
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
#endif

#include "grammar.h"
#include <cstring>
#include <algorithm>
#include "math.h"
#include "compiler.h"
#include "ast.h"
#include "log.h"
size_t yycolumn = 1;
void recordLocInfo(void)
{
    yylloc.first_line = yylineno;
    yylloc.last_line = yylineno;
    yylloc.first_column = yycolumn;
    yylloc.last_column = yycolumn + yyleng - 1;
    yycolumn = yylloc.last_column + 1;
}

int user_input(char* buf, int max_size)
{
    auto& textToParse = Compiler_t::getInst().getParseText();
    int sizeToRead = std::min(max_size, textToParse.length());
    if(0 != sizeToRead)
    {
        memcpy(buf, textToParse.toStdString().c_str(), sizeToRead);
    }
    textToParse.clear();
    return sizeToRead;
}

#define YY_USER_ACTION recordLocInfo();

#define YY_INPUT(buf,result,max_size) {result = user_input(buf, max_size);}
%}

NormalChar      [\+\-\*\/\(\)<>^%\[\]]
Number          [0-9]
HexNum          0x[0-9a-fA-F]+
Symbol          [a-zA-Z_][a-zA-Z0-9_]*
String          \".*\"
LineComment      \/\/.*
IgnoreChar      [ \t\r]
%%
if                                      return tk_kwIf;
else                                    return tk_kwEles;

index                                   {yylval.value = ASTDynamicNumber_t::VariableI; return tk_DynNum;};
t                                       {yylval.value = ASTDynamicNumber_t::VariableT; return tk_DynNum;};
N                                       {yylval.value = ASTDynamicNumber_t::VariableN; return tk_DynNum;};
fs                                      {yylval.value = ASTDynamicNumber_t::VariableFS; return tk_DynNum;};
pi                                      {yylval.value = M_PI; return tk_Number;}

\>=                                     return tk_opGequ;
\<=                                     return tk_opLequ;
\==                                     return tk_opEqu;
\!=                                     return tk_opNequ;

\&&                                     return tk_opBAnd;
\|\|                                    return tk_opBOr;

{NormalChar}                            return yytext[0];
{Number}+                               {yylval.value = atof(yytext); return tk_Number;}
{Number}+\.{Number}+                    {yylval.value = atof(yytext); return tk_Number;}
{HexNum}                                {
                                            char* endptr = NULL;
                                            yylval.value = strtol(yytext, &endptr, 0);
                                            //todo: what if *endptr is not '\0', what should we do?
                                            if(NULL == endptr) return YYerror;

                                            if(*endptr != '\0') {
                                                return YYerror;// is this enough?
                                            } else {
                                                return tk_Number;
                                            }
                                        }
{LineComment}                           {}
{Symbol}                                {yylval.id = strdup(yytext); return tk_Symbol;}
{String}                                {
                                            int len = yyleng - 1;
                                            char* str = (char*) malloc(len);
                                            memcpy(str, yytext + 1, len);
                                            str[len - 1] = '\0';
                                            yylval.id = str;
                                            return tk_String;
                                        }
{IgnoreChar}+                           {}
\n                                      {yycolumn = 1;}
#                                       return 0;
.                                       return yytext[0];
%%

/* int yywrap() 
{
    return 1;
} */

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
